import 'jquery';
import './popup.scss';

import React from 'react';
import ReactDom from 'react-dom';

import { cssPrefix } from '../baseData';

import Icon from '../icon/Icon.jsx';

import { Button } from '../button/Button.jsx';

import { PopupConfig, ConfirmConfig, InfoConfig, SuccessConfig, ErrorConfig, WarningConfig, LoadingConfig, MsgConfig } from './defaultConfig';

const IS_REACT_16 = !!ReactDom.createPortal;


export default class Popup extends React.Component{

  constructor(props){
    super(props);
    this.state = {
      ...PopupConfig
    }
  }

  cancelPopup(){
    let { onCancel } = this.state;
    this.setState({
      visible: false
    });

    typeof onCancel == 'function' && onCancel({...this.state});
  }

  cancelPopupByMask(e){
    let classNames = e.target.getAttribute('class');

    classNames && classNames.match(`${cssPrefix}popup-wrap`) && this.cancelPopup();
  }

  ok(){
    let { onOk } = this.state;
    if(typeof onOk == 'function'){
      onOk({...this.state}, this)
    }else{
      this.setState({
        visible: false
      })
    }
  }

  componentWillReceiveProps(props){
    this.setState({
      ...props
    })
  }

  componentWillMount() {
    this.setState({
      ...this.props
    })
  }

  componentDidMount(){

    this.state.keyboardEsc && $(document).on('keyup.ESC', (e)=>{
      if(e.keyCode == 27){
        this.cancelPopup()
      }
    })

  }

  componentWillUnmount(){
    this.state.keyboardEsc && $(document).off('keyup.ESC')
  }


  render(){
    let { visible, mask, maskClosable, maskStyle, bodyStyle, width, title, footer, okText, cancelText, okType, okButtonProps, cancelButtonProps, zIndex, closable, wrapClassName } = this.state,
      { popupFunType, iconType, content } = this.state, // popup function 特有参数
      hasTitle = !popupFunType && title;

    return <div className={wrapClassName}>
      {
        mask && <div
          className={`${cssPrefix}popup-mask${visible ? ` ${cssPrefix}popup-mask-hidden` : ''}`}
          style={{zIndex: zIndex, ...maskStyle}}>
        </div>
      }
      <div className={`${cssPrefix}popup-wrap${visible ? ` ${cssPrefix}popup-active` : ''}`} style={{zIndex: zIndex}} onClick={maskClosable ? this.cancelPopupByMask.bind(this) : ()=>{}} >
        <div className={`${cssPrefix}popup`} style={{width: width, ...bodyStyle}}>
          {
            closable && <div
              className={`${cssPrefix}popup-close${!hasTitle ? ` ${cssPrefix}popup-close-no-title` : ''}`}
              onClick={this.cancelPopup.bind(this)}
            ><Icon type={'close'} /></div>
          }
          {
            hasTitle && <div className={`${cssPrefix}popup-header`}>{title}</div>
          }
          <div className={`${cssPrefix}popup-body`}>

            {
              popupFunType
                ? (popupFunType == 'loading' || popupFunType == 'msg' )
                  ? <div className={`${cssPrefix}popup-${popupFunType}`}>
                  <div className={`${cssPrefix}popup-${popupFunType}-body`}>
                    {
                      popupFunType == 'loading' && <Icon type={iconType} spin />
                    }

                    {
                      popupFunType == 'msg' && <span>{ content }</span>
                    }

                  </div>
                </div>
                  : <div className={`${cssPrefix}popup-${popupFunType}`}>
                    <div className={`${cssPrefix}popup-${popupFunType}-body`}>
                      <Icon type={iconType} />
                      <span className={`${cssPrefix}popup-${popupFunType}-title`}>{ title }</span>
                      <div className={`${cssPrefix}popup-${popupFunType}-content`}>{ content }</div>
                    </div>
                    <div className={`${cssPrefix}popup-${popupFunType}-buttons`}>
                      {
                        popupFunType == 'confirm' && <Button type={'ghost'} size={'large'} {...cancelButtonProps} onClick={this.cancelPopup.bind(this)}>{cancelText}</Button>
                      }
                      <Button type={okType} size={'large'} {...okButtonProps} onClick={this.ok.bind(this)}>{okText}</Button>
                    </div>
                  </div>
                : this.props.children
            }

          </div>
          {
            footer && ( footer.constructor == Array
              ? <div className={`${cssPrefix}popup-footer`}>{footer}</div>
              : <div className={`${cssPrefix}popup-footer`}>
                <Button type={'ghost'} size={'large'} {...cancelButtonProps} onClick={this.cancelPopup.bind(this)}>{cancelText}</Button>
                <Button type={okType} size={'large'} {...okButtonProps} onClick={this.ok.bind(this)}>{okText}</Button>
              </div> )
          }
        </div>
      </div>
    </div>
  }
}


function confirm(config, defConfig) {
  typeof config == 'string' && ( config = {title: config} );

  const div = document.createElement('div');

  let currentConfig = { ...defConfig, ...config, ...{ close, visible: true } };

  currentConfig.container.style.position = 'relative';
  currentConfig.container.appendChild(div);

  function close(...args) {
    currentConfig = { ...currentConfig, visible: false, afterClose: destroy.bind(this, ...args) };
    if (IS_REACT_16) {
      render(currentConfig);
    } else {
      destroy(...args);
    }
  }
  function update(newConfig) {

    currentConfig = { ...currentConfig, ...newConfig, };

    render(currentConfig);
  }
  function destroy(...args) {
    const unmountResult = ReactDom.unmountComponentAtNode(div);
    if (unmountResult && div.parentNode) {
      div.parentNode.removeChild(div);
    }
    const triggerCancel = args && args.length &&
      args.some(param => param && param.triggerCancel);
    if (config.onCancel && triggerCancel) {
      config.onCancel(...args);
    }
  }
  function render(props) {
    ReactDom.render(<Popup {...props}/>, div);

    currentConfig.popupFunType == 'msg' && setTimeout(()=>{
      destroy()
    }, currentConfig.time)
  }
  render(currentConfig);
  return {
    close,
    destroy,
    update,
  };
}

Popup.loading = (props)=>{
  return confirm(props, LoadingConfig);
}

Popup.confirm = (props)=>{
  return confirm(props, ConfirmConfig);
}

Popup.info = (props)=>{
  return confirm(props, InfoConfig);
}

Popup.success = (props)=>{
  return confirm(props, SuccessConfig);
}

Popup.error = (props)=>{
  return confirm(props, ErrorConfig);
}

Popup.warning = (props)=>{
  return confirm(props, WarningConfig);
}

Popup.msg = (props)=>{
  typeof props == 'string' && (props={content: props});
  return confirm(props, MsgConfig);
}